import re
import time
from datetime import datetime

import pandas as pd
from selenium.common import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait

from compements.tool import is_similar


def validate_drug_conflicts(clicked_drugs, new_drug_name=None):
    """
    校验药品冲突，确保沙坦类和普利类药物不同时使用

    Args:
        clicked_drugs: 已选择的药品集合
        new_drug_name: 新添加的药品名称（可选）

    Returns:
        tuple: (is_valid, error_message)
    """
    # 合并当前药品和新药品（如果有的话）
    all_drugs = set(clicked_drugs)
    if new_drug_name:
        all_drugs.add(new_drug_name)

    # 分类药品
    shatan_drugs = [drug for drug in all_drugs if "沙坦" in drug]
    puli_drugs = [drug for drug in all_drugs if "普利" in drug]

    # 检查是否同时存在两类药品
    if shatan_drugs and puli_drugs:
        return False, f"不能同时使用沙坦类药物({', '.join(shatan_drugs)})和普利类药物({', '.join(puli_drugs)})"

    return True, ""
def introducing_outpatient_medication(driver, drug_counter, outpatient_drug_names_set, clicked_drugs,
                                      start_date, end_date):
    """
    引入门诊用药，使用统一的 '高血压糖尿病' sheet
    """
    # 点击加载门诊用药
    element = WebDriverWait(driver, 10).until(
        ec.visibility_of_element_located((By.XPATH, '//div[contains(text(), "加载门诊用药")]')))
    driver.execute_script("arguments[0].click();", element)
    time.sleep(6)

    try:
        # 等待所有匹配的元素出现
        yp = WebDriverWait(driver, 8).until(
            ec.presence_of_all_elements_located((By.XPATH,
                                                 "//div[contains(@class, 'x-grid-group ')]/div[2]/div/table/tbody/tr"))
        )
        yp_number = len(yp)
    except TimeoutException:
        yp_number = 0

    if yp_number == 0:
        print("门诊用药无用药需要引入")
        element = WebDriverWait(driver, 10).until(
            ec.visibility_of_element_located((By.XPATH, "//button[text()='选择']")))
        driver.execute_script("arguments[0].click();", element)
        return clicked_drugs
    else:
        print("开始引入门诊用药")
        for row in yp:

            drug_name = row.find_element(By.XPATH, './td[3]/div').text
            drug_name = drug_name.replace('（', '(').replace('）', ')')
            drug_name = re.sub(r'\(.*?\)', '', drug_name).strip()

            # 提取用药日期
            drug_date_text = row.find_element(By.XPATH, './td[6]/div').text
            if drug_date_text == '':
                continue

            drug_date = datetime.strptime(drug_date_text, "%Y-%m-%d")

            # 判断随访日期是否在指定范围内
            if start_date <= drug_date <= end_date:
                pass
            else:
                continue


            # 校验药品冲突
            is_valid, error_msg = validate_drug_conflicts(clicked_drugs, drug_name)
            if not is_valid:
                print(f"药品冲突警告: {error_msg}，跳过引入 {drug_name}")
                continue

            if is_similar(drug_name, clicked_drugs, threshold=0.6):# 忽略相似度
                if '磷酸西格列汀片' in clicked_drugs and drug_name=="达格列净片":
                    pass
                elif '达格列净片' in clicked_drugs and drug_name=="磷酸西格列汀片":
                    pass
                else:
                    continue
            if any(drug_name == re.sub(r'\(.*?$', '', name.replace('（', '(').replace('）', ')')).strip() for name in outpatient_drug_names_set) and drug_name not in clicked_drugs:
                print("正在引入门诊用药:", drug_name)

                # 点击药物
                drug_element = WebDriverWait(driver, 20).until(
                    ec.visibility_of_element_located((By.XPATH, f'//div[contains(text(), "{drug_name}")]')))
                driver.execute_script("arguments[0].scrollIntoView(true);", drug_element)
                time.sleep(1)

                # 模拟鼠标点击
                driver.execute_script("""
                    var evt = document.createEvent('MouseEvents');
                    evt.initMouseEvent('mousedown', true, true, window);
                    arguments[0].dispatchEvent(evt);
                    evt.initMouseEvent('mouseup', true, true, window);
                    arguments[0].dispatchEvent(evt);
                    evt.initMouseEvent('click', true, true, window);
                    arguments[0].dispatchEvent(evt);
                """, drug_element)
                time.sleep(1.5)
                clicked_drugs.add(drug_name)
                drug_counter += 1
                if drug_counter >= 5:
                    print("最多引入五个药品，停止引入")
                    break

        # 点击选择按钮
        element = WebDriverWait(driver, 10).until(
            ec.visibility_of_element_located((By.XPATH, "//button[text()='选择']")))
        driver.execute_script("arguments[0].click();", element)
        time.sleep(1.5)

    return clicked_drugs


def introducing_history_medication(driver, drug_counter, history_drug_names_set, clicked_drugs,
                                   start_date, end_date):
    """
    引入历史用药，使用动态选择的 sheet
    """
    # 点击加载历史用药
    element = WebDriverWait(driver, 10).until(
        ec.visibility_of_element_located((By.XPATH, '//div[contains(text(), "加载历史用药")]')))
    driver.execute_script("arguments[0].click();", element)
    time.sleep(6)

    try:
        # 等待所有匹配的元素出现
        yp = WebDriverWait(driver, 8).until(
            ec.presence_of_all_elements_located((By.XPATH,
                                                 "//div[contains(@class, 'x-grid-group ')]/div[2]/div/table/tbody/tr"))
        )
        yp_number = len(yp)
    except TimeoutException:
        yp_number = 0

    if yp_number == 0:
        print("历史用药无用药需要引入")
        element = WebDriverWait(driver, 10).until(
            ec.visibility_of_element_located((By.XPATH, "//button[text()='选择']")))
        driver.execute_script("arguments[0].click();", element)
        return clicked_drugs
    else:
        print("开始引入历史用药")
        any_drug_selected = False
        group_divs = WebDriverWait(driver, 10).until(
            ec.presence_of_all_elements_located((By.XPATH, "//div[contains(@class, 'x-grid-group ')]"))
        )

        for group_div in group_divs:
            # 提取随访日期标题
            follow_up_title_element = group_div.find_element(By.XPATH,
                                                             ".//div[contains(@class, 'x-grid-group-title')]")
            follow_up_title_text = follow_up_title_element.text
            if "随访日期" not in follow_up_title_text:
                continue

            # 提取随访日期
            follow_up_date_text = follow_up_title_text.split(":")[1].split("(")[0].strip()
            follow_up_date = datetime.strptime(follow_up_date_text, "%Y-%m-%d")
            if start_date <= follow_up_date <= end_date:
                print(f"随访日期 {follow_up_date_text} 在指定范围内")
            else:
                continue

            # 提取该块中的所有用药行
            rows = group_div.find_elements(By.XPATH,
                                           ".//table[@class='x-grid3-row-table']/tbody/tr")

            for row in rows:
                drug_name = row.find_element(By.XPATH, './td[3]/div').text
                drug_name = drug_name.replace('（', '(').replace('）', ')')
                drug_name = re.sub(r'\(.*?\)', '', drug_name).strip()

                # 校验药品冲突
                is_valid, error_msg = validate_drug_conflicts(clicked_drugs, drug_name)
                if not is_valid:
                    print(f"药品冲突警告: {error_msg}，跳过引入 {drug_name}")
                    continue

                if is_similar(drug_name, clicked_drugs, threshold=0.8):
                    continue
                if drug_name in history_drug_names_set and drug_name not in clicked_drugs:
                    print("正在引入历史用药:", drug_name)

                    # 点击药物
                    drug_element = WebDriverWait(driver, 20).until(
                        ec.visibility_of_element_located((By.XPATH, f'//div[contains(text(), "{drug_name}")]')))
                    driver.execute_script("arguments[0].scrollIntoView(true);", drug_element)
                    time.sleep(1)

                    # 模拟鼠标点击
                    driver.execute_script("""
                        var evt = document.createEvent('MouseEvents');
                        evt.initMouseEvent('mousedown', true, true, window);
                        arguments[0].dispatchEvent(evt);
                        evt.initMouseEvent('mouseup', true, true, window);
                        arguments[0].dispatchEvent(evt);
                        evt.initMouseEvent('click', true, true, window);
                        arguments[0].dispatchEvent(evt);
                    """, drug_element)
                    time.sleep(1.5)
                    clicked_drugs.add(drug_name)
                    any_drug_selected = True
                    drug_counter += 1

                    if drug_counter >= 5:
                        print("最多引入五个药品，停止引入")
                        break

        # 点击选择按钮
        element = WebDriverWait(driver, 10).until(
            ec.visibility_of_element_located((By.XPATH, "//button[text()='选择']")))
        driver.execute_script("arguments[0].click();", element)
        time.sleep(1.5)

    return clicked_drugs


def introducing_medication(driver, diseases_name, new_sf_data, sfzh):
    """
    主函数：先引入门诊用药，再引入历史用药
    """
    # 获取本季度已做过慢病随访，是否继续保存
    with open("./执行结果/env.txt", 'r', encoding='utf-8') as file:
        content = file.readlines()
    yes = content[5].replace("：", ":").split(":")[1].strip()
    print("本季度已做过慢病随访，是否继续保存:", yes)

    # 获取起止时间
    start_date = content[7].replace("：", ":").split(":")[1].strip()
    end_date = content[8].replace("：", ":").split(":")[1].strip()
    start_date = datetime.strptime(start_date, "%Y-%m-%d")
    end_date = datetime.strptime(end_date, "%Y-%m-%d")

    file_path = '文档/药品对照表.xlsx'

    # 门诊用药统一使用 "高血压糖尿病"
    sheet_name_outpatient = '高血压糖尿病'
    df_outpatient = pd.read_excel(file_path, sheet_name=sheet_name_outpatient)
    outpatient_drug_names_set = set(df_outpatient['产品名称'])
    outpatient_drug_names_set = {
        drug.replace('（', '(').replace('）', '') for drug in outpatient_drug_names_set
    }

    # 历史用药根据 diseases_name 动态选择 sheet
    if '高血压' in diseases_name and "糖尿病" not in diseases_name:
        sheet_name_history = '高血压'
    elif '高血压' not in diseases_name and "糖尿病" in diseases_name:
        sheet_name_history = '糖尿病'
    elif '高血压' in diseases_name and "糖尿病" in diseases_name:
        sheet_name_history = '高血压糖尿病'
    else:
        sheet_name_history = '高血压糖尿病'

    df_history = pd.read_excel(file_path, sheet_name=sheet_name_history)
    history_drug_names_set = set(df_history['产品名称'])
    history_drug_names_set = {
        drug.replace('（', '(').replace('）', '') for drug in history_drug_names_set
    }

    # 判断用药元素是否加载完成
    while True:
        try:
            element = WebDriverWait(driver, 10).until(
                ec.visibility_of_element_located((By.XPATH, '//div[contains(text(), "无")]')))
            if element.text == "无":
                print("用药情况正在引入")
                break
        except:
            pass

    clicked_drugs = set()  # 存储已点击的药品
    drug_counter = 0  # 引入药品计数器

    # 先尝试引入门诊用药（使用固定 sheet）
    clicked_drugs = introducing_outpatient_medication(
        driver, drug_counter, outpatient_drug_names_set, clicked_drugs, start_date, end_date
    )

    # 如果门诊用药为空，再尝试引入历史用药（使用动态 sheet）
    if not clicked_drugs:
        print("门诊用药中没有引入任何药品, 开始引入历史用药")
        clicked_drugs = introducing_history_medication(
            driver, drug_counter, history_drug_names_set, clicked_drugs, start_date, end_date
        )
    else:
        print("门诊用药已成功引入")

    # 点击用药保存
    element = WebDriverWait(driver, 10).until(
        ec.visibility_of_element_located((By.XPATH, '//*[@id="medSave"]/div/div[1]')))
    driver.execute_script("arguments[0].click();", element)
    time.sleep(1.5)
    skip = True

    try:
        element = WebDriverWait(driver, 3).until(
            ec.visibility_of_element_located((By.XPATH, '//span[contains(text(), "药品名称不能为空或无")]')))
        WebDriverWait(driver, 3).until(
            ec.visibility_of_element_located((By.XPATH, "//button[text()='确定']"))).click()


        return False
    except:
        pass

    try:
        # 获取本季度是否继续保存
        with open("./执行结果/env.txt", 'r', encoding='utf-8') as file:
            content = file.readlines()
        yes = content[5].replace("：", ":").split(":")[1].strip()
        element = WebDriverWait(driver, 3).until(
            ec.visibility_of_element_located((By.XPATH, "//span[contains(text(),'本季度已做过慢病随访')]")))
        element_yes = WebDriverWait(driver, 10).until(
            ec.visibility_of_element_located((By.XPATH, f"//button[text()='{yes}']")))
        driver.execute_script("arguments[0].click();", element_yes)
        if yes == '否':
            return False
    except TimeoutException:
        pass

    try:
        element = WebDriverWait(driver, 3).until(
            ec.visibility_of_element_located((By.XPATH, '//span[contains(text(), "需要先")]')))
        print("需要先保存随访，才能引入用药")
        time.sleep(.5)
        skip = False
        yes_element = WebDriverWait(driver, 10).until(
            ec.visibility_of_element_located((By.XPATH, '//button[contains(text(), "是")]')))
        driver.execute_script("""
            var element = arguments[0];
            var clickEvent = new MouseEvent('click', { bubbles: true });
            element.dispatchEvent(clickEvent);
            element.dispatchEvent(clickEvent);
        """, yes_element)
        WebDriverWait(driver, 3).until(
            ec.visibility_of_element_located((By.XPATH, "//button[text()='确定']"))).click()
        print("用药情况已保存")

        try:
            element = WebDriverWait(driver, 3).until(
                ec.visibility_of_element_located((By.XPATH, '//span[contains(text(), "是否加入到个人服务计划中")]')))
            WebDriverWait(driver, 3).until(
                ec.visibility_of_element_located((By.XPATH, '//button[contains(text(), "否")]'))).click()
        except:
            pass
    except:
        pass

    if skip:
        try:
            element = WebDriverWait(driver, 10).until(
                ec.visibility_of_element_located((By.XPATH, "//button[text()='确定']")))
            driver.execute_script("arguments[0].click();", element)
            print("用药情况已保存")
        except:
            print("用药情况点击保存无反应")

    return clicked_drugs
